package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.repository;

import com.alibaba.algo.cooperation.common.BaseResult;
import com.alibaba.algo.cooperation.feign.service.OrgFeignService;
import com.alibaba.algo.cooperation.feign.service.PositionFeignService;
import com.alibaba.algo.cooperation.feign.service.RoleFeignService;
import com.alibaba.algo.cooperation.feign.service.UserFeignService;
import com.alibaba.algo.cooperation.feign.vo.req.*;
import com.alibaba.algo.cooperation.feign.vo.res.*;
import com.aliyun.gts.bpaas.framework.api.rest.dto.ResultResponse;
import com.aliyun.gts.delivery.enterprise.sdk.common.PageQuery;
import com.aliyun.gts.delivery.enterprise.sdk.common.PageResult;
import com.aliyun.gts.delivery.enterprise.sdk.orgaccount.out.AccountInfo;
import com.aliyun.gts.delivery.enterprise.sdk.orgaccount.out.OrganizationInfo;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.UserEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.OrgAccountServiceAdapter;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.StringUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.common.FouraUser;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowUser;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.User;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.UserRepository;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowUserInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.entities.FlowUserInfoExample;
import com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.mapper.FlowUserInfoDAO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lilh
 * @date 2019-01-22 15:30
 */
@Service
@Slf4j
public class UserRepositoryImpl implements UserRepository {

    @Autowired
    private FlowUserInfoDAO flowUserInfoDAO;

    @Autowired
    PositionFeignService positionFeignService;

    @Autowired
    RoleFeignService roleFeignService;
    @Autowired
    OrgFeignService orgFeignService;
    @Autowired
    private OrgAccountServiceAdapter orgAccountService;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public User getCurrentUser() {
        ResultResponse<AccountInfo> currentAccountInfo = orgAccountService.getCurrentAccountInfo();
        FouraUser fouraUser = accountToFoura(currentAccountInfo.getData());
        User result = new User();
        BeanUtils.copyProperties(fouraUser, result);
        result.setId(-1);
        User user = getUserByCode(fouraUser.getUserCode());
        result.setUserType(Objects.nonNull(user) ? user.getUserType() : UserEnum.NORMAL.type());
        if (Objects.nonNull(user)) {
            result.setId(user.getId());
        }
        result.setOrgCode(fouraUser.getOrgCode());
        return result;
    }

    public FouraUser accountToFoura(AccountInfo accountInfo) {
        if (accountInfo == null) {
            return new FouraUser(null, null, null);
        }
        return new FouraUser((String) accountInfo.getExtentAttributes().get("USER_ID"),
                accountInfo.getUsername(), accountInfo.getCode(), (String) accountInfo.getExtentAttributes().get("ORG_CODE"),
                accountInfo.getMobilePhone());
    }

    @Override
    public User getUserById(String id) {
        FlowUserInfoExample userInfoExample = new FlowUserInfoExample();
        userInfoExample.createCriteria().andUserIdEqualTo(id);
        return getUserInfo(userInfoExample);
    }

    @Override
    public User getUserByCode(String userCode) {
        if (Objects.isNull(userCode)) {
            return null;
        }
        FlowUserInfoExample userInfoExample = new FlowUserInfoExample();
        userInfoExample.createCriteria().andUserCodeEqualTo(userCode);
        return getUserInfo(userInfoExample);
    }

    @Override
    public String getOrgNameByCode(String orgCode) {
        ResultResponse<OrganizationInfo> resultResponse = orgAccountService.getOrganizationByCode(orgCode);
        OrganizationInfo organizationInfo = resultResponse.getData();
        if (Objects.nonNull(organizationInfo)){
            return organizationInfo.getDisplayName();
        }
        return null;
    }

    @Override
    public User getUserWithOrgByCode(String userCode) {
        ResultResponse<AccountInfo> accountInfoByCode = orgAccountService.getAccountInfoByCode(userCode);
        FouraUser fouraUser = accountToFoura(accountInfoByCode.getData());
        User user = getUserByCode(fouraUser.getUserCode());
        if (!Objects.isNull(user)) {
            user.setOrgCode(fouraUser.getOrgCode());
        }
        return user;
    }

    @Override
    public User getUserWithOrgByCodeFromUserCenter(String userCode) {
        ResultResponse<AccountInfo> accountInfoByCode = orgAccountService.getAccountInfoByCode(userCode);
        if (accountInfoByCode.getData() == null) {
            return null;
        }
        FouraUser fouraUser = accountToFoura(accountInfoByCode.getData());
        User result = new User();
        BeanUtils.copyProperties(fouraUser, result);
        return result;
    }
    @Override

    public List<User> getUserByNameFromUserCenter(String userName) {
        ResultResponse<List<AccountInfo>> accountInfoByName = orgAccountService.getAccountByNameFuzzy(userName);
        if (accountInfoByName.getData() == null) {
            return null;
        }
        List<AccountInfo> list = accountInfoByName.getData();
        List<User> result=new ArrayList<>();
        list.forEach(item->{
            FouraUser fouraUser=accountToFoura(item);
            User user = new User();
            BeanUtils.copyProperties(fouraUser,user);
            result.add(user);
        });
        return result;
    }


    @Override
    public User getUserByName(String name) {
        FlowUserInfoExample userInfoExample = new FlowUserInfoExample();
        userInfoExample.createCriteria().andUserNameEqualTo(name);
        //*.andTenantIdEqualTo(tenantId)*/;
        return getUserInfo(userInfoExample);
    }

    @Override
    public Integer insertFlowUser(FlowUser userInfo) {
        FlowUserInfo entity = new FlowUserInfo();
        BeanUtils.copyProperties(userInfo, entity);
        entity.setCreateTime(new Date());
        entity.setUpdateTime(new Date());
        int count = flowUserInfoDAO.insertSelective(entity);
        userInfo.setId(entity.getId());
        return count;
    }

    @Override
    public List<FlowUser> listAppAuthorizedUser(Integer appId) {
        List<FlowUserInfo> flowUserInfos = flowUserInfoDAO.selectByAppId(appId);

        return getPageableResult(flowUserInfos);
    }

    private List<FlowUser> getPageableResult(List<FlowUserInfo> flowUsers) {
        PageInfo<FlowUserInfo> pageInfo = new PageInfo<>(flowUsers);
        Page<FlowUser> result = null;
        try {
            result = new Page<>();
            result.setPageNum(pageInfo.getPageNum()).setPageSize(pageInfo.getPageSize()).addAll(convert(flowUsers));
            result.setTotal(pageInfo.getTotal());
            return result;
        } finally {
            if (Objects.nonNull(result)) {
                result.close();
            }
        }
    }

    private List<FlowUser> convert(List<FlowUserInfo> flowUsers) {
        return flowUsers.stream().map(item -> {
            FlowUser user = new FlowUser();
            BeanUtils.copyProperties(item, user);
            return user;
        }).collect(Collectors.toList());
    }

    @Override
    public FlowUser insertFouraUser(FouraUser fouraUser) {
        FlowUser userInfo = new FlowUser();
        BeanUtils.copyProperties(fouraUser, userInfo);
        userInfo.setUserType(UserEnum.NORMAL.type());
        userInfo.setCreateTime(new Date());
        if (Objects.isNull(userInfo.getUserCode())) {
            logger.info("---无效用户信息：{}---", userInfo.toString());
            return null;
        }
        User current = getCurrentUserInfo();
        userInfo.setCreatorId(current.getId());
        userInfo.setCreatorName(current.getUserName());
        insertFlowUser(userInfo);
        return userInfo;
    }

    @Override
    public Integer updateFlowUser(FlowUser userInfo) {
        FlowUserInfo entity = new FlowUserInfo();
        BeanUtils.copyProperties(userInfo, entity);
        return flowUserInfoDAO.updateByPrimaryKeySelective(entity);
    }

    @Override
    public List<User> listUserByRoleId(String roleId) {
        ResultResponse<List<AccountInfo>> accountListByRoleId = orgAccountService.getAccountListByCode(roleId);
        log.info("get users from userCenterBy roleId-{}:{}",roleId,accountListByRoleId);
        List<User> result = new ArrayList<>();
        if(accountListByRoleId==null || accountListByRoleId.getData()==null){
            return result;
        }
       // List<FouraUser> fouraUsers = accountListToFouraList(accountListByRoleId.getData());
        List<AccountInfo> accountInfos=accountListByRoleId.getData();
//        for (FouraUser user : fouraUsers) {
//            User u = new User();
//            BeanUtils.copyProperties(user, u);
//            result.add(u);
//        }
        accountInfos.forEach(it->{
            User u = new User();
            u.setUserId(it.getCode());
            u.setUserName(it.getUsername());
            result.add(u);
        });
        return result;
    }

    public List<FouraUser> accountListToFouraList(List<AccountInfo> accountInfos) {
        List<FouraUser> fouraUsers = new ArrayList<>();
        for (AccountInfo accountInfo : accountInfos) {
            FouraUser fouraUser = new FouraUser((String) accountInfo.getExtentAttributes().get("USER_ID"),
                    accountInfo.getUsername(), accountInfo.getCode(), (String) accountInfo.getExtentAttributes().get("ORG_CODE"),
                    accountInfo.getMobilePhone());
            fouraUsers.add(fouraUser);
        }
        return fouraUsers;
    }

    @SuppressWarnings("unchecked")
    @Override
    public List<User> listUserByOrgCode(String orgCode) {
        //组织下有这么多人审核吗？
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNumber(10000);
        pageQuery.setPageSize(1);
        ResultResponse<PageResult<AccountInfo>> organizationMembersByOrgCode = orgAccountService.getOrganizationMembersByOrgCode(pageQuery, orgCode);
        List<User> result = new ArrayList<>();
        if(organizationMembersByOrgCode.getData()==null){
            return result;
        }
        List<AccountInfo> rows = organizationMembersByOrgCode.getData().getRows();

        if (CollectionUtils.isNotEmpty(rows)) {
            for (AccountInfo entry : rows) {
                User user = new User();
                //user.setUserId((String) entry.getExtentAttributes().get("USER_ID"));
                user.setUserId(entry.getCode());
                user.setUserCode(entry.getCode());
                user.setUserName(entry.getUsername());
                result.add(user);
            }
        }
        return result;
    }

    @Override
    public List<User> listUserByUserCodes(List<String> userCodes) {
        if (CollectionUtils.isEmpty(userCodes)) {
            return Collections.emptyList();
        }
        FlowUserInfoExample query = new FlowUserInfoExample();
        query.createCriteria().andUserCodeIn(userCodes);
        List<FlowUserInfo> flowUserInfos = flowUserInfoDAO.selectByExample(query);
        return flowUserInfos.stream().map(item -> {
            User user = new User();
            BeanUtils.copyProperties(item, user);
            return user;
        }).collect(Collectors.toList());
    }


    private User getUserInfo(FlowUserInfoExample userInfoExample) {
        List<FlowUserInfo> userInfos = flowUserInfoDAO.selectByExample(userInfoExample);
        if (CollectionUtils.isEmpty(userInfos)) {
            return null;
        }
        User user = new User();
        BeanUtils.copyProperties(userInfos.get(0), user);
        return user;
    }

    /**
     * 获取当前用户信息
     *
     * @return User
     */
    private User getCurrentUserInfo() {
        ResultResponse<AccountInfo> currentAccountInfo = orgAccountService.getCurrentAccountInfo();
        FouraUser fouraUser = accountToFoura(currentAccountInfo.getData());
        User user = getUserByCode(fouraUser.getUserCode());
        if (Objects.isNull(user)) {
            user = new User();
            BeanUtils.copyProperties(fouraUser, user);
            user.setId(-1);
        }
        user.setOrgCode(fouraUser.getOrgCode());
        return user;
    }

    @Override
    public List<User> getUserListByPositionId(String positionId){
        SelectPositionUserReqVO selectPositionUserReqVO=new SelectPositionUserReqVO();
        try{
            selectPositionUserReqVO.setPositionId(Long.valueOf(positionId));
        }
        catch(Exception e){
            log.error("the members of  positionId must be integer, please check the input positionId-{}",positionId);
            return null;
        }
        BaseResult<List<PositionUserInfoResVO>> positionsResult=positionFeignService.selectUserListByPosition(selectPositionUserReqVO);
        List<PositionUserInfoResVO>  positionsUsers=positionsResult.getData();
        List<User> users = new ArrayList<>();
        if(Objects.nonNull(positionsUsers)){
            positionsUsers.forEach(it->{
                if(it==null){
                    return;
                }
                User user=new User();
                user.setUserName(it.getUserName());
                user.setUserCode(String.valueOf(it.getUserId()));
                user.setEmployeeCode(it.getEmployeeCode());
                users.add(user);
                log.info("获取的用户信息：{}",user);
            });
        }
        return users;
    }

    /**
     * 根据岗位id获取岗位详细信息
     * @param positionId
     * @return
     */
    @Override
    public String getPositionDetailById(String positionId){
        GetPositionDetailVo getPositionDetailVo=new GetPositionDetailVo();
        try{
            getPositionDetailVo.setId(Long.valueOf(positionId));
        }
        catch(Exception e){
            log.error("the members of positionId must be integer, please check the input positionId-{}",positionId);
            return null;
        }
        BaseResult<FeignPositionDetailVo>  temp=positionFeignService.getPositionDetail(getPositionDetailVo);
        FeignPositionDetailVo feignPositionDetailVo=temp.getData();
        log.info("the position detail: {}",feignPositionDetailVo);
        if(feignPositionDetailVo==null){
            return null;
        }
        return feignPositionDetailVo.getName();
    }

    /**
     * 根据角色id获取角色名称
     * @param roleId
     * @return
     */
    @Override
    public String getRoleNameById(String roleId){
        GetRoleBaseInfoReqVO getRoleBaseInfoReqVO=new GetRoleBaseInfoReqVO();
        try{
            getRoleBaseInfoReqVO.setRoleId(Long.valueOf(roleId));
        }
        catch(Exception e){
            log.error("the members of roleId must be integer, please check the input positionId-{}",roleId);
            return null;
        }
        //app_code是必填项 先用bom试一下 在用mes来试
        getRoleBaseInfoReqVO.setAppCode("bom");
        BaseResult<RoleBaseInfoResponseVO> temp=roleFeignService.getRoleBaseInfoByIdOrCode(getRoleBaseInfoReqVO);
        if(temp.getData()==null){
            getRoleBaseInfoReqVO.setAppCode("mes");
            temp=roleFeignService.getRoleBaseInfoByIdOrCode(getRoleBaseInfoReqVO);
        }
        RoleBaseInfoResponseVO roleBaseInfoResponseVO=temp.getData();
        if(roleBaseInfoResponseVO==null){
            return null;
        }
        return roleBaseInfoResponseVO.getRoleName();
    }

    /**
     * 根据组织id获取组织名称
     * @param orgId
     * @return
     */
    @Override
    public String getOrgNameById(String orgId){
        GetOrgDetailReqVo getOrgDetailReqVo=new GetOrgDetailReqVo();
        try{
            getOrgDetailReqVo.setOrgId(Long.valueOf(orgId));
        }catch(Exception e){
            log.error("the members of roleId must be integer, please check the input orgId-{}",orgId);
            return null;
        }
        BaseResult<FeignOrgDetailResponse> temp=orgFeignService.getOrgDetail(getOrgDetailReqVo);
        if(temp.getData()==null){
            return null;
        }

        return temp.getData().getOrgName();
    }

}
